<!--
 * @Version: 1.0
 * @Author: ZPK
 * @Date: 2022-11-24 14:27:52
 * @LastEditors: ZPK
 * @LastEditTime: 2022-11-25 11:38:11
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        h1{
            display: block;
            width: 100%;
            margin: 0 auto;
            text-align: center;
        }
        div{
            padding: 5px;
        }
    </style>
</head>
<body>
   <div>
    <h1>Ts学习总结</h1>
        <header>使用ts开发的目的，为了安全以及更好的提示</header>
        <main>
            <h3>1.基本类型</h3>
            <div>
                1)字符串：这个很简单，但是需要注意的是string 和String是不同的，String可以描述实例
            </div>
            <div>
                2)数组：描述数组的有三种方式
                <div>
                    let a:Array"<"number">" = []
                </div>
                <div>
                    let b:number[]=[]
                </div>
                <div>
                    let c:(number|string)[]=[]
                </div>
            </div>
            <div>
                3)元组：和数组相似，只是得先定义好各个元素的属性
            </div>
            <div>
                4) 枚举enum
            </div>
            <div>
                5)null
            </div>
            <div>
                6)undefined
            </div>
            <div>
                7)void：空类型，用于函数的返回值
            </div>
            <div>
                8)never类型 任何类型的子类型 意味着 这个值不可能出现
            </div>
            <div>
                9)bigint
            </div>
            <div>
                10)object
            </div>
            <div>
                11)any
            </div>
            <div>
                12)字面量类型
                const userName:'js'='js'
                <div>
                    字面量类型常和联合类型放在一起用
                    type Direction = 'up' | 'down'
                    <br/>
                    let direction:Direction = 'up'
                </hr>
            </div>
            <div>
                13)unknown:unknown 和any 都是顶级类型   unknown是any的安全类型；any随意 不进行类型检测了；unknown还是要检测的  相对于any来说  在没有确定类型之前是不能操作的。不能当做函数 类  对象
            </div>
            <div>any是顶端类型  最大的类型</div>
            <div>
                never所有类型的子类型(低端类型) 如果这个值不需要可以将这个属性重置为never 完整性保护
            </div>
            <div>
                谁是谁的父级：类型的层级 never -- 字面量 -- 基本类型 -- 包装类型  Object  any/unknown
            </div>
        </main>
        <main>
            <h3>2.基本语法</h3>
            <div>
                联合类型 |  let strOrNum:string|number
            </div>
            <div>
                联合类型 & 其实是合并
            </div>
            <div>
                非空断言 !  strOrNum!.toString()
            </div>
            <div>
                类型断言 as (strOrNum! as string).toLocaleLowerCase()  
                <br/>
                 另一种写法("<"number">"strOrNum!).toFixed(2)
                <div>
                    注意：断言只能断言一个已经存在的类型，如果不存在不能直接断言
                    strOrNum! as any as boolean
                </div>
            </div>
            <div>
                <div>
                    typeof：取变量的类型 返回的是类型
                    <div>
                        keyof：去的是类型的key的集合
                    </div>
                    <div>
                        const person = {name:'js',age:30}
                    </div>
                    <div>
                        type Person = typeof person 
                        得到的是{
                            name:string,
                            age:number
                        }
                    </div>
                    <div>
                        typeof PersonKey = keyof Person
                            得到的是
                            “name”|"string"
                    </div>
                    <div>
                        type PropTypeUnion = keyof Person 得到的是key name | age
                    </div>
                    <div>
                        type PropTypeValueUnion = Person[keyof Person] 取值string | number
                    </div>
                </div>
                <div>
                    
                </div>
            </div>
        </main>
        <main>
            <h3>3.函数</h3>
            <div>
                函数的声明方式有两种： 
                <div>
                    function关键字声明:
                function sum(a:string,b:string):string{
                    return a+b
                }
                </div>
                <div>
                    表达式声明：
                    type Sum = (x:string,y:string)=>string
                    let sum1:Sum=function(a:string,b:string):string{
                        return a+b
                    }
                    <br/>
                    let sum2:{(x?:string,y?:string):string}=function(a:string,b:string):string{
                        return a+b
                    }
                </div>
                <div>
                    函数重载：后端的定义就是定义一些同名的方法，通过定义不同的输入来区分一些方法。js不支持函数的重载，ts也就不支持，所以ts中的函数重载称为伪重载，js是通过arguments来重载的
                    <div>
                        function toArray(value:number):number[]
                    </div>
                    <div>
                        function toArray(value:string):string[]
                    </div>
                    <div>
                        function toArray(value:string|number):string[]|number[]{
                            ...
                        }
                    </div>
                </div>
            </div>
        </main>
        <main>
            <h3>4.类的基本用法</h3>
            <div>
                类：类的组成部分，构造函数，属性(实例属性，原型属性)，方法(实例方法，原型方法：访问器)
            </div>
            <div>
                类的修饰符：public(公开的：我自己，我的儿子，外界)、protected(受保护的：我自己，我儿子)、private(私有的：我自己)、readonly(只读的)
            </div>
            <div>
                super关键字：代表的是父类 或者父类的原型
            </div>
            <div>
                子类中重写父类的方法：1）要求必须和父类的方法类型一致，2）使用void不关心返回值，只有在类中可以这样
                <hr>
                class Animal{
                    say():void{}
                }
                <hr>
                class Mouse extends Animal{
                    say():string{
                        return 'abc'
                    }
                }
            </div>
        </main>
        <main>
            <h3>5.interface接口</h3>
            <div>type和interface的区别</div>
            <div>
                interface通常描述对象 类的结构比较多。优点：可重名，重名会合并，可继承 混合类型
                <br>
                type描述函数的签名，联合类型 工具类型 映射条件类型等
            </div>
            <div>
                使用interface遇到可有可无的属性该如何处理？
                <ul>
                    <li>
                        1.直接as断言 但是不能取多余的属性 因为不知道有没有
                    </li>
                    <li>2.采用可选属性来标示?</li>
                    <li>
                        3.我在基于当前类型声明一个新的类型
                    </li>
                    <li>
                        4.同名接口可以合并
                    </li>
                    <li>
                        5.[xxx:string]:any 任意类型
                    </li>
                </ul>
                <div>
                    interface IVer {
                        color:string,
                        taste:stirng,
                        size:number,
                        [key:string]:any
                    }
                    <br>
                    interface IvegWith extends Iver{
                        readonly xx?:number
                     }
                </div>
                <div>
                    可以通过索引访问符号 来防范接口中的属性类型。注意：这里面不能用点.来取值
                    type ITest = Iver["color"]
                </div>
                <div>
                    interface Speakable{
                        name:stirng,
                        speak:()=>void 
                        speak():void
                    }
                    <div>第一个方法是实例上的方法，下面的是原型上的方法,但是ts区分不开</div>
                </div>
                <div>
                    interface SpeakChinese{
                        speakChines():void
                    }
                </div>
                <div>
                    class Speak <strong>implements</strong> Speakable ,SpeakChinese{
                        name!:string
                        speak(): void {
                            throw new Error('AA')
                        }
                        speakChines():void{
                            throw new Error('BB')
                        }
                    }
                </div>
                <div>
                    类：当做类型的时候，描述的是实例。想要获取到类本身的类型，需要采用typeof获取
                </div>
                <div>
                    class Person{}
                    function createInstance(clazz:keyof Person):Person{
                        return new clazz()
                    }
                    let instatance = createInstance(Person)
                </div>
            </div>
        </main>
        <main>
            <h3>6.泛型</h3>
            <div>
                <div>泛型放的位置不同，意思不同</div>
                <img src="./image/泛型.jpg" alt="">
            </div>
            <div>
                泛型可以指定默认值 默认泛型 给泛型增加了默认值。常用extends来对泛型进行约束
            </div>
        </main>
        <main>
            <h3>7.内置类型</h3>
            <div>
                条件类型  extends 约束 经常和条件类型一起使用
                type ResStatus"<"T"> = T extends 200 | 201 | ? 'success' : 'fail'
            </div>
            <div>
                Extract、Exclued 、NonNullable、ReturnType、Parameters、InstanceType、Pick、Omit、Record(用于取代object)、Partial、Required、修饰符：readonly、- ? 
            </div>
            <div>
                <ul>
                    <li>
                        Exclude Extract集合的操作
                    </li>
                    <li>
                        Pick Omit 对对象结构的操作
                    </li>
                    <li>
                        Partial Required Readonly  起修饰作用的
                    </li>
                    <li>
                        ReturnType Paramaters InstanceType ... (基于infer)
                    </li>
                </ul>
            </div>
        </main>
        <main>
            <h3>8.分发机制</h3>
            <div>
                分发机制：
                <ul>
                    <li>1.通过泛型传入的方式来比较的时候会出现分发</li>
                    <li>2.且传入的类型需要是联合类型</li>
                    <li>3.类型完全的裸露出来</li>
                </ul>
                <div>缺点：在判断谁是谁的子类型时，就会发生异常</div>
                <div>如何避免分发：</div>
                <div>
                    <img src="./image/分发.jpg" alt="">
                </div>
            </div>
        </main>
        <main>
            <h3>9.类型推断 infer</h3>
            <div>
                <img src="./image/类型推断.jpg" alt="">
            </div>
        </main>
        <main>
            <h3>10.兼容性问题</h3>
            <div>
                父子关系 不要考虑谁多谁少  考虑的是父子类型的层级关系 哟啊从安全考虑
            </div>
            <div>
                逆变：子->父;
                协变：父->子;
                参数：逆变，返回值：协变 ---> 传父返子
            </div>
        </main>
        <main>
            <h3>11.类型推断</h3>
            <div>
                类型推断是从右边向左边
                <ul>
                    <li>
                        1)赋值推断
                    </li>
                    <li>
                        2)函数返回值
                    </li>
                    <li>
                        3)反向推断 从左向右
                        <div>
                            <img src="./image/类型推断.jpg" alt="">
                        </div>
                        
                    </li>
                </ul>
            </div>
        </main>
        <main>
            <h3>12.类型保护</h3>
            <div>
                类型保护：js+ts
                <ul>
                    <li>1.js) typeof、instanceof、in</li>
                    <li>
                        <div>2.ts) is语法</div>
                        <img src="./image/is语法.jpg" alt="">
                    </li>
                </ul>
            </div>
        </main>
        <main>
            <h3>13.小技巧</h3>
            <div>
                <div>如何判断两个类型完全相等</div>
                <div>
                    <img src="./image/相等.jpg" alt="">
                </div>
                <div>遍历出类型内部的属性和值</div>
                <div>
                    <img src="./image/compute.jpg" alt="">
                </div>
            </div>
        </main>
        <main>
            <h3>14.自定义属性</h3>
            <div>
                <img src="./image//自定义属性.jpg" alt="">
            </div>
        </main>
   </div>
</body>
</html>